﻿#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
/***************1.内存分区模型******************/
//C++程序在执行时，将内存大方向划分为**4个区域**
//- 代码区：存放函数体的二进制代码，由操作系统进行管理的
//- 全局区：存放全局变量和静态变量以及常量
//- 栈区：由编译器自动分配释放, 存放函数的参数值, 局部变量等
//- 堆区：由程序员分配和释放, 若程序员不释放, 程序结束时由操作系统回收

/******程序运行前*******/
//在程序编译后，生成了exe可执行程序，**未执行该程序前**分为两个区域
//** 代码区：**
//​		存放 CPU 执行的机器指令
//​		代码区是** 共享** 的，共享的目的是对于频繁被执行的程序，只需要在内存中有一份代码即可
//​		代码区是** 只读** 的，使其只读的原因是防止程序意外地修改了它的指令

//​** 全局区：**
//​		全局变量和静态变量存放在此.
//​		全局区还包含了常量区, 字符串常量和其他常量也存放在此.
//		该区域的数据在程序结束后由操作系统释放.

////全局变量
//int g_a = 10;
//int g_b = 10;
//
////const修饰的全局变量
//const int c_g_a = 10;
//const int c_g_b = 10;
//
//int main()
//{
//	//全局区
//
//	//全局变量、静态变量、常量
//
//	//局部变量 -- 不在全局区
//	int a = 10;
//	int b = 10;
//	cout << "局部变量a的地址为：" << &a << endl;
//	cout << "局部变量b的地址为：" << &b << endl;
//
//	//全局变量
//	cout << "全局变量g_a的地址为：" << &g_a << endl;
//	cout << "全局变量g_b的地址为：" << &g_b << endl;
//
//	//静态变量
//	static int s_a = 10; 
//	static int s_b = 10;
//	cout << "静态变量s_a的地址为：" << &s_a << endl;
//	cout << "静态变量s_b的地址为：" << &s_b << endl;
//
//	//常量
//	//字符串常量
//	cout << "字符串常量的地址为：" << &"hehe" << endl;
//
//	//const修饰的变量
//	//const修饰的全局变量
//	cout << "const修饰的全局变量c_g_a的地址为：" << &c_g_a << endl;
//	cout << "const修饰的全局变量c_g_b的地址为：" << &c_g_b << endl;
//
//	//const修饰的局部变量 -- 不在全局区
//	int c_l_a = 10;
//	int c_l_b = 10;
//	cout << "const修饰的局部变量c_l_a的地址为：" << &c_l_a << endl;
//	cout << "const修饰的局部变量c_l_b的地址为：" << &c_l_b << endl;
//
//
//	system("pause");
//	return 0;
//}

//总结
//* 全局区中存放全局变量、静态变量、常量
//* 常量区中存放 const修饰的全局常量  和 字符串常量


/********程序运行后*********/
//** 栈区 **
//由编译器自动分配释放, 存放函数的参数值, 局部变量等
//注意事项：不要返回局部变量的地址，栈区开辟的数据由编译器自动释放

//int* func(int b) //形参也在栈区
//{
//	b = 100;
//	int a = 10;
//	return &a; //返回地址是错误的，出函数局部变量会销毁
//}
//
//int main()
//{
//	int* p = func();
//	cout << *p << endl; //第一次正确因为编译器做了保留
//	cout << *p << endl; //这次数据不再保留
//
//	system("pause");
//	return 0;
//}

//堆区
//由程序员分配释放, 若程序员不释放, 程序结束时由操作系统回收
//在C++中主要利用new在堆区开辟内存
//int* func()
//{
//	//利用new关键字,可以将数据开辟到堆区
//	//这个p依旧是在栈区是局部变量，它存的地址是在堆区里
//	int* p = new int(10);
//	return p;
//}
//
//int main()
//{
//	//在堆区开辟数据
//	int* p = func();
//	cout << *p << endl;
//	cout << *p << endl;
//
//
//	system("pause");
//	return 0;
//}

//总结
//堆区数据由程序员管理开辟和释放
//堆区数据利用new关键字进行开辟内存

/********new操作符**********/
////C++中利用*new*操作符在堆区开辟数据
//​//堆区开辟的数据，由程序员手动开辟，手动释放。
//​//利用new创建的数据，会返回该数据对应的类型的指针
////释放利用操作符 * delete *;

//int* func()
//{
//	int* p = new int(10);
//	return p;
//}
//
//void test01()
//{
//	int* p = func();
//	cout << *p << endl;
//	//堆区数据由程序员手动开辟，手动释放。
//	delete p;//释放内存
//}
//
//void test02()
//{
//	//堆区创建数组
//	int* arr = new int[10];
//	for (int i = 0; i < 10; i++)
//	{
//		arr[i] = i + 100;
//	}
//
//	for (int i = 0; i < 10; i++)
//	{
//		cout << arr[i] << endl;
//	}
//
//	//释放堆区数组
//	//释放数组要加[]
//	delete[] arr;
//}
//
//int main()
//{
//	test01();
//	test02();
//	//new的基本语法
//	
//	//在堆区利用new开辟数组
//	system("pause");
//	return 0;
//}

/********************2.引用********************/
//引用的基本使用
//作用：给变量起别名
//语法 数据类型 &别名 = 原名
//int main()
//{
//	int a = 10;
//	int& b = a;
//
//	cout << a << endl;
//	cout << b << endl;
//	
//	b = 20;
//
//	cout << a << endl;
//	cout << b << endl;
//
//	system("pause");
//	return 0;
//}

//引用注意事项
//引用必须初始化
//引用在初始化后，不可改变
//int main()
//{
//	int a = 10;
//	int b = 20;
//	//int& c; //错误，引用必须初始化
//
//	int& c = a;
//
//	c = b; //赋值操作，不是更改引用
//
//	//int& c = b; //错误，引用初始化后，不可以改变
//	cout << c << endl;
//
//	system("pause");
//	return 0;
//}

//引用做函数参数
//作用：函数传参时,可以利用引用让形参修饰实参
//
//值传递
//void myswap( int x, int y)
//{
//	int temp = x;
//	x = y;
//	y = temp;
//}
//
////地址传递
//void myswap2(int* x, int* y)
//{
//	int temp = *x;
//	*x = *y;
//	*y = temp;
//}
//
////引用传递
//void myswap3(int& x, int& y) //x,y使用引用相当于a,b的别名
//{
//	int temp = x;
//	x = y;
//	y = temp;
//}
//
//int main()
//{
//	int a = 10;
//	int b = 20;
//
//	//myswap(a,b);//值传递
//	//cout << a << endl;
//	//cout << b << endl;
//
//	//myswap2(&a, &b);//地址传递
//	//cout << a << endl;
//	//cout << b << endl;
//
//	myswap3(a , b); //引用传递 -- 会交换实参
//	cout << a << endl;
//	cout << b << endl;
//
//	system("pause");
//	return 0;
//}

//引用做函数返回值
//1.注意不要返回局部变量引用
//int& test01()
//{
//	int a = 10; //局部变量存放在栈区
//	return a; //注意不要返回局部变量引用
//}
////
////2.函数地调用可以作为左值
//int& test02()
//{
//	static int a = 10; //静态变量存放在全局区,不会出函数释放
//	return a;
//}
//
//int main()
//{
//	//int& ref = test01();
//	//cout << ref << endl; //非法操作
//	//cout << ref << endl; //非法操作
//
//	int& ref2 = test02();
//	cout << ref2 << endl;
//
//	test02() = 1000; //如果函数的返回值是引用，这个函数地调用可以作为左值
//	cout << ref2 << endl;
//
//	system("pause");
//	return 0;
//}

//引用的本质
//本质：引用的本质在c++内部实现是一个指针常量
//指针常量:指向不可以修改，指向的值可以修改
// 
//发现是引用，转换为 int* const ref = &a;
//void func(int& ref) 
//{
//	ref = 100; // ref是引用，转换为*ref = 100
//}
//
//int main()
//{
//	//指针常量：
//	/*int a = 10;
//	int b = 20;
//	int* const p = &a;
//	*p = 30;
//	cout << *p << endl;*/
//
//	int a = 10;
//	//自动转换为 int* const ref = &a; 指针常量是指针指向不可改，也说明为什么引用不可更改
//	int& ref = a;
//	ref = 20; //内部发现ref是引用，自动帮我们转换为: *ref = 20;
//
//	cout << "a:" << a << endl; //20
//	cout << "ref:" << ref << endl; //20
//
//	func(a);
//	cout << "a:" << a << endl; //100
//
//	system("pause");
//	return 0;
//}

//常量引用
// 作用：常量引用主要来修饰形参,防止误操作
//void showvalue(const int& val)
//{
//	//val = 120; //const修饰的形参，不可修改
//
//	cout << "val = " << val << endl;
//}
//
//int main()
//{
//	//int a = 10;
//	//int& ref = a; // int* const ref = &a
//
//	//int& ref2 = 20; // 错误,引用本身需要一个合法的内存空间
//	//const int& ref2 = 20; //加入const就可以了，编译器优化代码，int temp = 10; const int& ref = temp;
//
//	//ref2 = 30; //错误，因为加const，不可以修改变量
//	//cout << ref2 << endl;
//
//	int a = 100;
//	showvalue(a);
//
//
//	system("pause");
//	return 0;
//}



